package com.cskaoyan.controller;

import com.cskaoyan.bean.BaseRespVo;
import com.cskaoyan.bean.MarketStorage;
import com.cskaoyan.bean.param.BaseParam;
import com.cskaoyan.bean.param.CommonData;
import com.cskaoyan.config.StorageProperties;
import com.cskaoyan.config.zhangshizhi.CountTime;
import com.cskaoyan.service.StorageService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartResolver;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;

/**
 * 用于处理文件存储相关的请求
 * <p>
 * 在品牌制造商和商品类目中上传图片都会发送相同的请求路径，
 * 故将其暂时作为独立的一个Controller，也许其他业务中也会用到
 * <p>
 * 使用时注意文件的保存路径，因为采用的是文件路径，也就是盘符的形式，
 * TODO：暂时默认定位在 "D:\mall2_storage\fetch\" 目录中
 *
 * @author Chen_Feng
 * @since 2022/06/26 12:33
 */
@RestController
@RequestMapping("admin/storage")
public class StorageController {

    @Autowired
    StorageService storageService;

    @Autowired
    StorageProperties storageProperties;

    /**
     * 对上传的文件保存到本地，并将有关信息记录到 market_storage 数据库
     *
     * @param file 上传的文件经过SpringBoot封装处理后生成对象
     * @return com.cskaoyan.bean.BaseRespVo<com.cskaoyan.bean.MarketStorage>
     * @author Chen_Feng
     * @since 2022/06/26 16:05
     */
    @CountTime
    @RequiresPermissions(value = {"admin:storage:create", "*"}, logical = Logical.OR)
    @RequestMapping("create")
    public BaseRespVo<MarketStorage> storageCreate(MultipartFile file) {

        // 从file中获取信息并封装成MarketStorage对象
        MarketStorage storage = multipartFile2MarketStorage(file);

        /*
        // 文件大小校验
        int maxSize = 10485760;
        if (storage.getSize() > maxSize) {
            return BaseRespVo.invalidParameter("文件最大不超过10mb");
        }
        */

        // TODO：指定保存路径的父目录，默认 "D:\mall2_storage\fetch" 目录，请自行调整
        File parentFile = new File(storageProperties.getSaveParentPath());

        // 父目录不存在则创建目录
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }

        // 执行Service层业务，将相关信息保存至数据库
        MarketStorage returnStorage = null;
        try {
            returnStorage = storageService.create(storage);
        } catch (Exception e) {
            e.printStackTrace();
            return BaseRespVo.invalidData("信息保存异常");
        }

        // 保存文件（图片）
        String fileName = returnStorage.getKey() + returnStorage.getName().substring(returnStorage.getName().lastIndexOf("."));
        File saveFile = new File(parentFile, fileName);
        try {
            file.transferTo(saveFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 图片路径处理，增加ip(域名) + 端口
        returnStorage.setUrl(storageProperties.getOrigin() + returnStorage.getUrl());

        // 返回响应
        return BaseRespVo.ok(returnStorage);
    }

    /**
     * 将MultipartFile对象中的信息取出封装成MarketStorage对象的辅助方法
     *
     * @param file 请求中获取到的MultipartFile对象
     * @return com.cskaoyan.bean.MarketStorage
     * @author Chen_Feng
     * @since 2022/06/26 16:22
     */
    private MarketStorage multipartFile2MarketStorage(MultipartFile file) {

        // 获取文件名、html标签对应的name属性值、文件MIME类型、文件大小
        String originalFilename = file.getOriginalFilename();
        String name = file.getName();
        String contentType = file.getContentType();
        long size = file.getSize();

        // 为文件名增加一定前缀保证文件不同名
        String key = UUID.randomUUID().toString();
        String fileName = key + originalFilename.substring(originalFilename.lastIndexOf("."));

        // 封装数据
        MarketStorage storage = new MarketStorage();
        storage.setKey(key);
        storage.setName(originalFilename);
        storage.setType(contentType);
        storage.setSize((int) size);
        storage.setUrl(storageProperties.getPreUri() + fileName);
        Date date = new Date();
        storage.setAddTime(date);
        storage.setUpdateTime(date);
        storage.setDeleted(false);

        // 返回结果
        return storage;
    }

    /**
     * 对象存储 list
     * @author zhangsenqi
     * @param baseParam
     * @return
     */
    @CountTime
    @RequiresPermissions(value = {"admin:storage:list", "*"}, logical = Logical.OR)
    @RequestMapping("list")
    public BaseRespVo<CommonData<MarketStorage>> storageList(BaseParam baseParam, String key,String name){
        CommonData<MarketStorage> commonData = storageService.list(baseParam, key, name);
        return BaseRespVo.ok(commonData);
    }

    /**
     * 对象存储 update
     * @author zhangsenqi
     * @param marketStorage
     * @return
     */
    @CountTime
    @RequiresPermissions(value = {"admin:storage:update", "*"}, logical = Logical.OR)
    @PostMapping("update")
    public BaseRespVo<MarketStorage> storageUpdate(@RequestBody MarketStorage marketStorage){
        storageService.update(marketStorage);
        return BaseRespVo.ok(marketStorage);
    }

    /**
     * 对象存储 delete
     * @param marketStorage
     * @return
     * @author zhangsenqi
     */
    @CountTime
    @RequiresPermissions(value = {"admin:storage:delete", "*"}, logical = Logical.OR)
    @PostMapping("delete")
    public BaseRespVo<MarketStorage> storageDelete(@RequestBody MarketStorage marketStorage){
        storageService.delete(marketStorage);
        return BaseRespVo.ok(null);
    }

}
